package com.xue.rpc.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.util.Arrays;

import com.xue.rpc.common.RpcMapping;
import com.xue.rpc.protos.RPC;

/**
 * 
 * @author 北京八维博大科技 薛建新
 * @date 2022年9月3日 下午2:23:14
 * @Copyright 北京八维博大科技
 */
public class RpcHandler implements InvocationHandler {
	private SocketClient rpcClient;

	public RpcHandler() {
		this.rpcClient = new SocketClient();
	}

	@SuppressWarnings("unchecked")
	public <T> T getProxy(Class<?>... classArray) {
		return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), classArray, this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String baseUri = method.getDeclaringClass().getAnnotation(RpcMapping.class).uri();
		// 1.获取方法上注解
		String path = method.getDeclaredAnnotation(RpcMapping.class).uri();
		// 2.获取注解uri
		URI uri = new URI(baseUri + path);
		// 3.组装参数
		var rpcArgs = Arrays.stream(args).map((arg) -> {
			return RPC.Request.Arg.newBuilder().setType(arg.getClass().toString()).setValue(String.valueOf(arg))
					.build();
		}).toList();
		// 4. 构建请求
		var rpcRequest = RPC.Request.newBuilder().setUri(uri.getPath()).addAllArg(rpcArgs).build();
		// 5. 发起调用并等待返回
		var rpcResponse = RPC.Response
				.parseFrom(rpcClient.call(uri.getHost(), uri.getPort(), rpcRequest.toByteArray()));
		// 6. 包装返回结果
		return Integer.valueOf(rpcResponse.getValue());
	}

}
